/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.northwestern.cbits.activitydetector.app; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks; import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener; import com.google.android.gms.location.ActivityRecognitionClient; import android.app.Activity; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.util.Log; /** * Class for connecting to Location Services and removing activity recognition updates. * <b> * Note: Clients must ensure that Google Play services is available before removing activity * recognition updates. * </b> Use GooglePlayServicesUtil.isGooglePlayServicesAvailable() to check. * * * To use a DetectionRemover, instantiate it, then call removeUpdates(). * */ public class DetectionRemover implements ConnectionCallbacks, OnConnectionFailedListener { // Storage for a context from the calling client private Context mContext; // Stores the current instantiation of the activity recognition client private ActivityRecognitionClient mActivityRecognitionClient; // The PendingIntent sent in removeUpdates() private PendingIntent mCurrentIntent; /** * Construct a DetectionRemover for the current Context * * @param context A valid Context */ public DetectionRemover(Context context) { // Save the context mContext = context; // Initialize the globals to null mActivityRecognitionClient = null; } /** * Remove the activity recognition updates associated with a PendIntent. The PendingIntent is * the one used in the request to add activity recognition updates. * * @param requestIntent The PendingIntent used to request activity recognition updates */ public void removeUpdates(PendingIntent requestIntent) { /* * Set the request type, store the List, and request a activity recognition client * connection. */ mCurrentIntent = requestIntent; // Continue the removal by requesting a connection requestConnection(); } /** * Request a connection to Location Services. This call returns immediately, * but the request is not complete until onConnected() or onConnectionFailure() is called. */ private void requestConnection() { getActivityRecognitionClient().connect(); } /** * Get the current activity recognition client, or create a new one if necessary. * * @return An ActivityRecognitionClient object */ public ActivityRecognitionClient getActivityRecognitionClient() { /* * If a client doesn't already exist, create a new one, otherwise * return the existing one. This allows multiple attempts to send * a request without causing memory leaks by constantly creating * new clients. * */ if (mActivityRecognitionClient == null) { // Create a new one setActivityRecognitionClient(new ActivityRecognitionClient(mContext, this, this)); } return mActivityRecognitionClient; } /** * Get a activity recognition client and disconnect from Location Services */ private void requestDisconnection() { // Disconnect the client getActivityRecognitionClient().disconnect(); // Set the client to null setActivityRecognitionClient(null); } /** * Set the global activity recognition client * @param client An ActivityRecognitionClient object */ public void setActivityRecognitionClient(ActivityRecognitionClient client) { mActivityRecognitionClient = client; } /* * Called by Location Services once the activity recognition client is connected. * * Continue by removing activity recognition updates. */ @Override public void onConnected(Bundle connectionData) { // If debugging, log the connection Log.d(ActivityUtils.APPTAG, mContext.getString(R.string.connected)); // Send a request to Location Services to remove activity recognition updates continueRemoveUpdates(); } /** * Once the connection is available, send a request to remove activity recognition updates. */ private void continueRemoveUpdates() { // Remove the updates mActivityRecognitionClient.removeActivityUpdates(mCurrentIntent); /* * Cancel the PendingIntent. This stops Intents from arriving at the IntentService, even if * request fails. */ mCurrentIntent.cancel(); // Disconnect the client requestDisconnection(); } /* * Called by Location Services once the activity recognition client is disconnected. */ @Override public void onDisconnected() { // In debug mode, log the disconnection Log.d(ActivityUtils.APPTAG, mContext.getString(R.string.disconnected)); // Destroy the current activity recognition client mActivityRecognitionClient = null; } /* * Implementation of OnConnectionFailedListener.onConnectionFailed * If a connection or disconnection request fails, report the error * connectionResult is passed in from Location Services */ @Override public void onConnectionFailed(ConnectionResult connectionResult) { /* * Google Play services can resolve some errors it detects. * If the error has a resolution, try sending an Intent to * start a Google Play services activity that can resolve * error. */ if (connectionResult.hasResolution()) { try { connectionResult.startResolutionForResult((Activity) mContext, ActivityUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); /* * Thrown if Google Play services canceled the original * PendingIntent */ } catch (SendIntentException e) { // display an error or log it here. } /* * If no resolution is available, display Google * Play service error dialog. This may direct the * user to Google Play Store if Google Play services * is out of date. */ } else { Dialog dialog = GooglePlayServicesUtil.getErrorDialog( connectionResult.getErrorCode(), (Activity) mContext, ActivityUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); if (dialog != null) { dialog.show(); } } } }